home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / LAPB < prev    next >
Text File  |  1994-03-03  |  28KB  |  701 lines

  1. /* Link Access Procedures Balanced (LAPB) - with changes for rational
  2.  * behavior over packet radio
  3.  */
  4. #include <string.h>
  5. #include <time.h>
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "timer.h"
  9. #include "ax25.h"
  10. #include "netrom.h"
  11. #include "ip.h"
  12. #include "lapb.h"
  13.  
  14. static int  ackours(struct ax25_cb *, char);
  15. static void procdata(struct ax25_cb *, struct mbuf *);
  16. static void desegment(struct mbuf *, struct ax25_cb *);
  17.  
  18. /* Process incoming frames */
  19. int lapb_input(struct ax25_cb *axp, char cmdrsp, struct mbuf *bp)
  20. {
  21.         char control;
  22.         char class;             /* General class (I/S/U) of frame */
  23.         int16 type;             /* Specific type (I/RR/RNR/etc) of frame */
  24.         char pf;                /* extracted poll/final bit */
  25.         char poll = 0;
  26.         char final = 0;
  27.         int nr;                 /* ACK number of incoming frame */
  28.         int ns;                 /* Seq number of incoming frame */
  29.         char tmp;
  30.  
  31.         if(bp == NULLBUF || axp == NULLAX25){
  32.                 free_p(bp);
  33.                 return -1;
  34.         }
  35.  
  36.         /* Extract the various parts of the control field for easy use */
  37.         control = pullchar(&bp);
  38.         type = ftype(control);
  39.         class = type & 0x3;
  40.         pf = control & PF;
  41.         /* Check for polls and finals */
  42.         if(pf){
  43.                 switch(cmdrsp){
  44.                 case COMMAND:
  45.                         poll = YES;
  46.                         break;
  47.                 case RESPONSE:
  48.                         final = YES;
  49.                         break;
  50.                 }
  51.         }
  52.         /* Extract sequence numbers, if present */
  53.         switch(class){
  54.         case I:
  55.         case I+2:
  56.                 ns = (control >> 1) & MMASK;
  57.         case S: /* Note fall-thru */
  58.                 nr = (control >> 5) & MMASK;
  59.                 break;
  60.         }
  61.         /* This section follows the SDL diagrams by K3NA fairly closely */
  62.         switch(axp->state){
  63.         case DISCONNECTED:
  64.                 switch(type){
  65.                 case SABM:      /* Initialize or reset link */
  66.                         sendctl(axp,RESPONSE,UA|pf);    /* Always accept */
  67.                         clr_ex(axp);
  68.                         axp->unack = axp->vr = axp->vs = 0;
  69.                         lapbstate(axp,CONNECTED);/* Resets state counters */
  70.                         start_timer(&axp->t3);
  71.                         start_timer(&axp->t4);
  72.                         break;
  73.                 case DM:        /* Ignore to avoid infinite loops */
  74.                         break;
  75.                 default:        /* All others get DM only if POLL set */
  76.                         if(poll)
  77.                                 sendctl(axp,RESPONSE,DM|pf);
  78.                         break;
  79.                 }
  80.                 break;
  81.         case SETUP:
  82.                 switch(type){
  83.                 case SABM:      /* Simultaneous open */
  84.                         sendctl(axp,RESPONSE,UA|pf);
  85.                         break;
  86.                 case DISC:
  87.                         sendctl(axp,RESPONSE,DM|pf);
  88.                         free_q(&axp->txq);
  89.                         stop_timer(&axp->t1);
  90.                         lapbstate(axp,DISCONNECTED);
  91.                         break;
  92.                 case UA:        /* Connection accepted */
  93.                         /* Note: xmit queue not cleared */
  94.                         stop_timer(&axp->t1);
  95.                         start_timer(&axp->t3);
  96.                         axp->unack = axp->vr = axp->vs = 0;
  97.                         lapbstate(axp,CONNECTED);
  98.                         start_timer(&axp->t4);
  99.                         break;                  
  100.                 case DM:        /* Connection refused */
  101.                         free_q(&axp->txq);
  102.                         stop_timer(&axp->t1);
  103.                         lapbstate(axp,DISCONNECTED);
  104.                         break;
  105.                 default:        /* All other frames ignored */
  106.                         break;
  107.                 }
  108.                 break;
  109.         case DISCPENDING:
  110.                 switch(type){
  111.                 case SABM:
  112.                         sendctl(axp,RESPONSE,DM|pf);
  113.                         stop_timer(&axp->t1);
  114.                         lapbstate(axp,DISCONNECTED);
  115.                         break;
  116.                 case DISC:
  117.                         sendctl(axp,RESPONSE,UA|pf);
  118.                         stop_timer(&axp->t1);
  119.                         lapbstate(axp,DISCONNECTED);
  120.                         break;
  121.                 case UA:
  122.                 case DM:
  123.                         stop_timer(&axp->t1);
  124.                         lapbstate(axp,DISCONNECTED);
  125.                         break;
  126.                 default:        /* Respond with DM only to command polls */
  127.                         if(poll){
  128.                                 sendctl(axp,RESPONSE,DM|pf);
  129.                                 stop_timer(&axp->t1);
  130.                                 lapbstate(axp,DISCONNECTED);
  131.                                 }
  132.                         break;
  133.                 }
  134.                 break;
  135.         case CONNECTED:
  136.                 switch(type){
  137.                 case SABM:
  138.                         sendctl(axp,RESPONSE,UA|pf);
  139.                         clr_ex(axp);
  140.                         free_q(&axp->txq);
  141.                         stop_timer(&axp->t1);
  142.                         start_timer(&axp->t3);
  143.                         axp->unack = axp->vr = axp->vs = 0;
  144.                         lapbstate(axp,CONNECTED); /* Purge queues */
  145.                         break;
  146.                 case DISC:
  147.                         free_q(&axp->txq);
  148.                         sendctl(axp,RESPONSE,UA|pf);
  149.                         stop_timer(&axp->t1);
  150.                         stop_timer(&axp->t3);
  151.                         lapbstate(axp,DISCONNECTED);
  152.                         break;
  153.                 case UA:
  154.                         break;
  155.                 case DM:
  156.                 case FRMR:
  157.                         est_link(axp);
  158.                         lapbstate(axp,SETUP);   /* Re-establish link */
  159.                         break;
  160.                 case RR:
  161.                 case RNR:
  162.                         axp->remotebusy = (control == RNR) ? YES : NO;
  163.                         if(poll)
  164.                                 enq_resp(axp);
  165.                         if(ackours(axp,nr) != 0)
  166.                                 {
  167.                                 frmr(axp,control,Z); /* invalid n(r) */
  168.                                 lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  169.                                 start_timer(&axp->t1);
  170.                                 break;
  171.                                 }
  172.                         break;
  173.                 case REJ:
  174.                         axp->remotebusy = NO;
  175.                         if(poll)
  176.                                 enq_resp(axp);
  177.                         if(ackours(axp,nr) != 0)
  178.                                 {
  179.                                 frmr(axp,control,Z); /* invalid n(r) */
  180.                                 lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  181.                                 start_timer(&axp->t1);
  182.                                 break;
  183.                                 }
  184.                         stop_timer(&axp->t1);
  185.                         start_timer(&axp->t3);
  186.                         /* This may or may not actually invoke transmission,
  187.                          * depending on whether this REJ was caused by
  188.                          * our losing his prior ACK.
  189.                          */
  190.                         inv_rex(axp);
  191.                         break;  
  192.                 case I:
  193.                         if(ackours(axp,nr) != 0)
  194.                                 {
  195.                                 frmr(axp,control,Z); /* invalid n(r) */
  196.                                 lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  197.                                 start_timer(&axp->t1);
  198.                                 break;
  199.                                 }
  200.                         start_timer(&axp->t4);
  201.                         if(len_mbuf(axp->rxq) >= axp->window){
  202.                                 /* Too bad he didn't listen to us; he'll
  203.                                  * have to resend the frame later. This
  204.                                  * drastic action is necessary to avoid
  205.                                  * deadlock.
  206.                                  */
  207.                                 if(poll)
  208.                                         sendctl(axp,RESPONSE,RNR|pf);
  209.                                 free_p(bp);
  210.                                 bp = NULLBUF;
  211.                                 break;
  212.                         }
  213.                         /* Reject or ignore I-frames with receive sequence number errors */
  214.                         if(ns != axp->vr){
  215.                                 if(axp->proto == V1 || !axp->rejsent){
  216.                                         axp->rejsent = YES;
  217.                                         sendctl(axp,RESPONSE,REJ | pf);
  218.                                 }
  219.                                 axp->response = 0;
  220.                                 stop_timer(&axp->t2);
  221.                                 break;
  222.                         }
  223.                         axp->rejsent = NO;
  224.                         axp->vr = (axp->vr+1) & MMASK;
  225.                         tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  226.                         if(poll){
  227.                                 sendctl(axp,RESPONSE,tmp|PF);
  228.                         } else {
  229.                                 axp->response = tmp;
  230.                                 start_timer(&axp->t2);
  231.                         }
  232.                         procdata(axp,bp);
  233.                         bp = NULLBUF;
  234.                         break;
  235.                 default:        /* All others frame rejected..invalid frame */
  236.                         frmr(axp,control,W);
  237.                         lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  238.                         start_timer(&axp->t1);
  239.                         break;
  240.                 }
  241.                 break;
  242.         case RECOVERY:
  243.                 switch(type){
  244.                 case SABM:
  245.                         sendctl(axp,RESPONSE,UA|pf);
  246.                         clr_ex(axp);
  247.                         stop_timer(&axp->t1);
  248.                         start_timer(&axp->t3);
  249.                         axp->unack = axp->vr = axp->vs = 0;
  250.                         lapbstate(axp,CONNECTED); /* Purge queues */
  251.                         if(!run_timer(&axp->t4))
  252.                                 start_timer(&axp->t4);
  253.                         break;
  254.                 case DISC:
  255.                         free_q(&axp->txq);
  256.                         sendctl(axp,RESPONSE,UA|pf);
  257.                         stop_timer(&axp->t1);
  258.                         stop_timer(&axp->t3);
  259.                         axp->response = UA;
  260.                         lapbstate(axp,DISCONNECTED);
  261.                         break;
  262.                 case UA:
  263.                 case DM:
  264.                 case FRMR:
  265.                         est_link(axp);
  266.                         lapbstate(axp,SETUP);   /* Re-establish link */
  267.                         break;
  268.                 case RR:
  269.                 case RNR:
  270.                         axp->remotebusy = (control == RNR) ? YES : NO;
  271.                         if(axp->proto == V1 || final){
  272.                                 stop_timer(&axp->t1);
  273.                                 if(ackours(axp,nr) != 0)
  274.                                         {
  275.                                         frmr(axp,control,Z); /* invalid n(r) */
  276.                                         lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  277.                                         start_timer(&axp->t1);
  278.                                         break;
  279.                                         }
  280.                                 if(axp->unack != 0){
  281.                                         inv_rex(axp);
  282.                                 } else {
  283.                                         start_timer(&axp->t3);
  284.                                         lapbstate(axp,CONNECTED);
  285.                                         if(!run_timer(&axp->t4))
  286.                                                 start_timer(&axp->t4);
  287.                                 }
  288.                         } else {
  289.                                 if(poll)
  290.                                         enq_resp(axp);
  291.                                 if(ackours(axp,nr) != 0)
  292.                                         {
  293.                                         frmr(axp,control,Z); /* invalid n(r) */
  294.                                         lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  295.                                         start_timer(&axp->t1);
  296.                                         break;
  297.                                         }
  298.                                 /* Keep timer running even if all frames
  299.                                  * were acked, since we must see a Final
  300.                                  */
  301.                                 if(!run_timer(&axp->t1))
  302.                                         start_timer(&axp->t1);
  303.                         }
  304.                         break;
  305.                 case REJ:
  306.                         axp->remotebusy = NO;
  307.                         /* Don't insist on a Final response from the old proto */
  308.                         if(axp->proto == V1 || final){
  309.                                 stop_timer(&axp->t1);
  310.                                 if(ackours(axp,nr) != 0)
  311.                                         {
  312.                                         frmr(axp,control,Z); /* invalid n(r) */
  313.                                         lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  314.                                         start_timer(&axp->t1);
  315.                                         break;
  316.                                         }
  317.                                 if(axp->unack != 0){
  318.                                         inv_rex(axp);
  319.                                 } else {
  320.                                         start_timer(&axp->t3);
  321.                                         lapbstate(axp,CONNECTED);
  322.                                         if(!run_timer(&axp->t4))
  323.                                                 start_timer(&axp->t4);
  324.                                 }
  325.                         } else {
  326.                                 if(poll)
  327.                                         enq_resp(axp);
  328.                                 if(ackours(axp,nr) != 0)
  329.                                         {
  330.                                         frmr(axp,control,Z); /* invalid n(r) */
  331.                                         lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  332.                                         start_timer(&axp->t1);
  333.                                         break;
  334.                                         }
  335.                                 if(axp->unack != 0){
  336.                                         /* This is certain to trigger output */
  337.                                         inv_rex(axp);
  338.                                 }
  339.                                 /* A REJ that acks everything but doesn't
  340.                                  * have the F bit set can cause a deadlock.
  341.                                  * So make sure the timer is running.
  342.                                  */
  343.                                 if(!run_timer(&axp->t1))
  344.                                         start_timer(&axp->t1);
  345.                         }
  346.                         break;
  347.                 case I:
  348.                         if(ackours(axp,nr) != 0)
  349.                                 {
  350.                                 frmr(axp,control,Z); /* invalid n(r) */
  351.                                 lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  352.                                 start_timer(&axp->t1);
  353.                                 break;
  354.                                 }
  355.                         /* Make sure timer is running, since an I frame
  356.                          * cannot satisfy a poll
  357.                          */
  358.                         if(!run_timer(&axp->t1))
  359.                                 start_timer(&axp->t1);
  360.                         if(len_mbuf(axp->rxq) >= axp->window){
  361.                                 /* Too bad he didn't listen to us; he'll
  362.                                  * have to resend the frame later. This
  363.                                  * drastic action is necessary to avoid
  364.                                  * memory deadlock.
  365.                                  */
  366.                                 sendctl(axp,RESPONSE,RNR | pf);
  367.                                 free_p(bp);
  368.                                 bp = NULLBUF;
  369.                                 break;
  370.                         }
  371.                         /* Reject or ignore I-frames with receive sequence number errors */
  372.                         if(ns != axp->vr){
  373.                                 if(axp->proto == V1 || !axp->rejsent){
  374.                                         axp->rejsent = YES;
  375.                                         sendctl(axp,RESPONSE,REJ | pf);
  376.                                 }
  377.                                 axp->response = 0;
  378.                                 stop_timer(&axp->t2);
  379.                                 break;
  380.                         }
  381.                         axp->rejsent = NO;
  382.                         axp->vr = (axp->vr+1) & MMASK;
  383.                         tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  384.                         if(poll){
  385.                                 sendctl(axp,RESPONSE,tmp|PF);
  386.                         } else {
  387.                                 axp->response = tmp;
  388.                                 start_timer(&axp->t2);
  389.                         }
  390.                         procdata(axp,bp);
  391.                         bp = NULLBUF;
  392.                         break;
  393.                 default:
  394.                         frmr(axp,control,W);    /* invalid frame */
  395.                         lapbstate(axp,FRAMEREJECT); /* enter frame reject state */
  396.                         start_timer(&axp->t1);
  397.                         break;          
  398.                 }
  399.                 break;
  400.         case FRAMEREJECT:
  401.                 switch(type){
  402.                 case SABM:
  403.                         sendctl(axp,RESPONSE,UA|pf);
  404.                         clr_ex(axp);
  405.                         axp->unack = axp->vr = axp->vs = 0;
  406.                         stop_timer(&axp->t1);
  407.                         start_timer(&axp->t3);
  408.                         lapbstate(axp,CONNECTED);
  409.                         if(!run_timer(&axp->t4))
  410.                                 start_timer(&axp->t4);
  411.                         break;
  412.                 case DISC:
  413.                         free_q(&axp->txq);
  414.                         sendctl(axp,RESPONSE,UA|pf);
  415.                         stop_timer(&axp->t1);
  416.                         lapbstate(axp,DISCONNECTED);
  417.                         break;
  418.                 case DM:
  419.                         stop_timer(&axp->t1);
  420.                         lapbstate(axp,DISCONNECTED);
  421.                         break;
  422.                 case FRMR:
  423.                         est_link(axp);
  424.                         lapbstate(axp,SETUP);   /* Re-establish link */
  425.                         break;
  426.                 default:        /* Respond with FRMR only to command polls */
  427.                         if(poll)
  428.                                 {
  429.                                 frmr(axp,0,0);
  430.                                 start_timer(&axp->t1);
  431.                                 }
  432.                         break;
  433.                 }
  434.                 break;
  435.         }
  436.         free_p(bp);     /* In case anything's left */
  437.  
  438.         /* See if we can send some data, perhaps piggybacking an ack.
  439.          * If successful, lapb_output will clear axp->response.
  440.          */
  441.         lapb_output(axp);
  442.  
  443.         /* Empty the trash */
  444.         if(axp->state == DISCONNECTED)
  445.                 del_ax25(axp);
  446.         return 0;
  447. }
  448. /* Handle incoming acknowledgements for frames we've sent.
  449.  * Free frames being acknowledged.
  450.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  451.  */
  452. static int ackours(struct ax25_cb *axp, char n)
  453. {       
  454.         struct mbuf *bp;
  455.         int acked = 0;  /* Count of frames acked by this ACK */
  456.         int oldest;     /* Seq number of oldest unacked I-frame */
  457.  
  458.         /* Free up acknowledged frames by purging frames from the I-frame
  459.          * transmit queue. Start at the remote end's last reported V(r)
  460.          * and keep going until we reach the new sequence number.
  461.          * If we try to free a null pointer,
  462.          * then we have a frame reject condition.
  463.          */
  464.         oldest = (axp->vs - axp->unack) & MMASK;
  465.         while(axp->unack != 0 && oldest != n){
  466.                 if((bp = dequeue(&axp->txq)) == NULLBUF){
  467.                         /* Acking unsent frame */
  468.                         return -1;
  469.                 }
  470.                 free_p(bp);
  471.                 axp->unack--;
  472.                 acked++;
  473.                 axp->retries = 0;
  474.                 oldest = (oldest + 1) & MMASK;
  475.         }
  476.         if(axp->unack == 0){
  477.                 /* All frames acked, stop timeout */
  478.                 stop_timer(&axp->t1);
  479.                 start_timer(&axp->t3);
  480.         } else if(acked != 0) { 
  481.                 /* Partial ACK; restart timer */
  482.                 start_timer(&axp->t1);
  483.         }
  484.         /* If user has set a transmit upcall, indicate how many frames
  485.          * may be queued
  486.          */
  487.         if(acked != 0 && axp->t_upcall != NULLVFP)
  488.                 (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  489.  
  490.         return 0;
  491. }
  492.  
  493. /* Establish data link */
  494. void est_link(struct ax25_cb *axp)
  495. {
  496.         clr_ex(axp);
  497.         axp->retries = 0;
  498.         sendctl(axp,COMMAND,SABM|PF);
  499.         stop_timer(&axp->t3);
  500.         start_timer(&axp->t1);
  501. }
  502. /* Clear exception conditions */
  503. void clr_ex(struct ax25_cb *axp)
  504. {
  505.         axp->remotebusy = NO;
  506.         axp->rejsent = NO;
  507.         axp->response = 0;
  508.         stop_timer(&axp->t3);
  509. }
  510. /* Enquiry response */
  511. void enq_resp(struct ax25_cb *axp)
  512. {
  513.         char ctl;
  514.  
  515.         ctl = len_mbuf(axp->rxq) >= axp->window ? RNR|PF : RR|PF;       
  516.         sendctl(axp,RESPONSE,ctl);
  517.         axp->response = 0;
  518.         stop_timer(&axp->t3);
  519. }
  520. /* Invoke retransmission */
  521. void inv_rex(struct ax25_cb *axp)
  522. {
  523.         axp->vs -= axp->unack;
  524.         axp->vs &= MMASK;
  525.         axp->unack = 0;
  526. }
  527. /* Generate Frame Reject (FRMR) response
  528.  * If reason != 0, this is the initial error frame
  529.  * If reason == 0, resend the last error frame
  530.  */
  531. int frmr(register struct ax25_cb *axp, char control, char reason)
  532. {
  533.         struct mbuf *frmrinfo;
  534.         register char *cp;
  535.  
  536.         if(reason != 0){
  537.                 cp = axp->frmrinfo;
  538.                 *cp++ = control;
  539.                 *cp++ =  axp->vr << 5 | axp->vs << 1;
  540.                 *cp = reason;
  541.         }
  542.         if((frmrinfo = alloc_mbuf(3)) == NULLBUF)
  543.                 return -1;      /* No memory */
  544.         frmrinfo->cnt = 3;
  545.         memcpy(frmrinfo->data,axp->frmrinfo,3);
  546.         return sendframe(axp,RESPONSE,FRMR|(control&PF),frmrinfo);
  547. }
  548.  
  549. /* Send S or U frame to currently connected station */
  550. int sendctl(struct ax25_cb *axp, char cmdrsp, char cmd)
  551. {
  552.         if((ftype(cmd) & 0x3) == S)     /* Insert V(R) if S frame */
  553.                 cmd |= (axp->vr << 5);
  554.         return sendframe(axp,cmdrsp,cmd,NULLBUF);
  555. }
  556. /* Start data transmission on link, if possible
  557.  * Return number of frames sent
  558.  */
  559. int lapb_output(register struct ax25_cb *axp)
  560. {
  561.         register struct mbuf *bp;
  562.         struct mbuf *tbp;
  563.         char control;
  564.         int sent = 0;
  565.         int i;
  566.  
  567.         if(axp == NULLAX25
  568.          || (axp->state != RECOVERY && axp->state != CONNECTED)
  569.          || axp->remotebusy)
  570.                 return 0;
  571.  
  572.         /* Dig into the send queue for the first unsent frame */
  573.         bp = axp->txq;
  574.         for(i = 0; i < axp->unack; i++){
  575.                 if(bp == NULLBUF)
  576.                         break;  /* Nothing to do */
  577.                 bp = bp->anext;
  578.         }
  579.         /* Start at first unsent I-frame, stop when either the
  580.          * number of unacknowledged frames reaches the maxframe limit,
  581.          * or when there are no more frames to send
  582.          */
  583.         while(bp != NULLBUF && axp->unack < axp->maxframe){
  584.                 control = I | (axp->vs++ << 1) | (axp->vr << 5);
  585.                 axp->vs &= MMASK;
  586.                 dup_p(&tbp,bp,0,len_mbuf(bp));
  587.                 if(tbp == NULLBUF)
  588.                         return sent;    /* Probably out of memory */
  589.                 sendframe(axp,COMMAND,control,tbp);
  590.                 start_timer(&axp->t4);
  591.                 axp->unack++;
  592.                 /* We're implicitly acking any data he's sent, so stop any
  593.                  * delayed ack
  594.                  */
  595.                 axp->response = 0;
  596.                 stop_timer(&axp->t2);
  597.                 if(!run_timer(&axp->t1)){
  598.                         stop_timer(&axp->t3);
  599.                         start_timer(&axp->t1);
  600.                 }
  601.                 sent++;
  602.                 bp = bp->anext;
  603.         }
  604.         return sent;
  605. }
  606. /* Set new link state.
  607.  * If the new state is disconnected, also free the link control block.
  608.  */
  609. void lapbstate(struct ax25_cb *axp, int s)
  610. {
  611.         int oldstate;
  612.  
  613.         oldstate = axp->state;
  614.         axp->state = s;
  615.         if(s == DISCONNECTED){
  616.                 stop_timer(&axp->t1);
  617.                 stop_timer(&axp->t2);
  618.                 stop_timer(&axp->t3);
  619.                 stop_timer(&axp->t4);
  620.                 free_q(&axp->txq);
  621.         }
  622.         /* Don't bother the client unless the state is really changing */
  623.         if(oldstate != s && axp->s_upcall != NULLVFP)
  624.                 (*axp->s_upcall)(axp,oldstate,s);
  625. }
  626. /* Process a valid incoming I frame */
  627. static void procdata(struct ax25_cb *axp, struct mbuf *bp)
  628. {
  629.         char pid;
  630.  
  631.         /* Extract level 3 PID */
  632.         if(pullone(&bp,&pid) != 1)
  633.                 return; /* No PID */
  634.  
  635.         switch(pid){
  636.         case PID_IP:            /* DoD Internet Protocol */
  637.                 ip_route(bp,0);
  638.                 break;
  639.         case PID_NO_L3:         /* Enqueue for application */
  640.                 append(&axp->rxq,bp);
  641.                 if(axp->r_upcall != NULLVFP)
  642.                         (*axp->r_upcall)(axp,len_mbuf(axp->rxq));
  643.                 break;  
  644.         case PID_NETROM:
  645.                 nr_route(bp,axp);
  646.                 break;
  647.         case PID_SEGMENT:
  648.                 desegment(bp,axp);
  649.                 break;
  650.         default:                /* Note: ARP is invalid here */ 
  651.                 free_p(bp);
  652.                 break;                  
  653.         }
  654. }
  655. /* TODO This code assumes all segments are in order. The code elsewehere
  656.  * doesn't allow for segmented UI IP, therefore AX25 connected mode is used
  657.  * which means the segments can't get out of order, can they ?
  658.  */  
  659. static void desegment(struct mbuf *bp, struct ax25_cb *axp)
  660. {                    
  661.         char segment;
  662.  
  663.         /* Extract offset */
  664.         if(pullone(&bp,&segment) != 1)
  665.                 return; /* No Data !! */
  666.  
  667.         if(segment & SEG_FIRST){
  668.                 /* "Shouldn't happen", but flush any accumulated frags */
  669.                 free_p(axp->rxasm);
  670.                 axp->rxasm = NULLBUF;
  671.                 /* Extract embedded PID */
  672.                 if(pullone(&bp,&axp->segpid) != 1)
  673.                         return;
  674.         }
  675.  
  676.         append(&axp->rxasm,bp);
  677.  
  678.         if((segment & SEG_REM) == 0){
  679.                 /* Last frame of multi-frame message; extract it */
  680.                 bp = axp->rxasm;
  681.                 axp->rxasm = NULLBUF;
  682.  
  683.                 switch(axp->segpid){
  684.                 case PID_IP:            /* DoD Internet Protocol */
  685.                         ip_route(bp,0);
  686.                         break;
  687.                 case PID_NO_L3:         /* Enqueue for application */
  688.                         append(&axp->rxq,bp);
  689.                         if(axp->r_upcall != NULLVFP)
  690.                                 (*axp->r_upcall)(axp,len_mbuf(axp->rxq));
  691.                         break;  
  692.                 case PID_NETROM:
  693.                         nr_route(bp,axp);
  694.                         break;
  695.                 default:                /* Note: ARP is invalid here */ 
  696.                         free_p(bp);
  697.                         break;   
  698.                 }
  699.         }
  700. }
  701.